import { App } from "../App";
import { Singleton } from "./Class";

/**
 * CSV 文件解析
 * 文件格式
 * 第一行:列说明
 * 第二行:列数据类型
 * 第三行:数据起始行
 */
/*
    csv文件解析
    （默认）样式一
    line0:类型定义
    line1:数据类型 
    line2:数据值
*/

enum CsvEnum{
    Doc=0,   // 行数
    Type=1,
    Key=2,
    Data=3,
}

export default class CSVFile extends Singleton<CSVFile>{
    
    // isKeyValTab:是否是样式二表格数据
    public load(file:string,callback:(data:any)=>void,isKeyValTab:boolean=false):void{        
        if (App.Util.isEmpty(file)){
            console.warn(`load csv file[${file}]is error`);
            return ;
        }
        if (file.split(':').length > 1){
            App.Res.loadRes(file,cc.Asset,(res:cc.TextAsset)=>{
                const dt:any = this._toJSON(res.text,file,isKeyValTab);
                if (App.Util.isValid(dt)){
                    callback && callback(dt);
                }
            });
        } else {
            App.Res.loadResources(file,cc.Asset,(res:cc.TextAsset)=>{
                const dt:any = this._toJSON(res.text,file,isKeyValTab);
                if (App.Util.isValid(dt)){
                    callback && callback(dt);
                }
            });
        }
    }

    private _toJSON(data:string,file:string,isKeyValTab:boolean):any{
        if (App.Util.isEmpty(data) || data.split('\n').length < CsvEnum.Data+1)
            return null;

        const CSV:string[] =  data.replace(/\r/g,'').split('\n');

        if (isKeyValTab) return this._toJSON_KV(CSV);

        const Type:string[] = CSV[CsvEnum.Type].split(',').slice(0);
        const Key:string[] = CSV[CsvEnum.Key].split(',').slice(0);
        console.assert(Type.length === Key.length,`load ${file} is error.`);

        let json:any = [];    
        for (let i = CsvEnum.Data; i < CSV.length; ++i){
            const line:any = CSV[i].split(',');
            if (App.Util.isInvalid(line[0])) continue ;

            let _data:any = {};
            for (let j = 0; j < Key.length; ++j)
                _data[Key[j]]=this._getValue(Type[j],line[j]);
                json.push(_data);
        }
        
        return json;
    }

    private _getValue(type:string,val:string):any{
        type = type.toLocaleLowerCase();
        if (type === 'number' || type === 'date')
            return parseInt(val);
        else if (type === 'boolean')
            return val.toLocaleLowerCase() === 'true';
        else if (type === 'userdata') return Object(val);
        else if (type === 'array'){
            if (App.Util.isInvalid(val)) return [];
            let _tmp = val.split('|');
            let _data:any = [];
            for (let i in _tmp) _data[i] = _tmp[i];
            return _data;
        }

        return val && val.toString();
    }

    private _toJSON_KV(csvData:any):any{
        let json:any = [];    
        for (let i = 1; i < csvData.length; ++i){
            const Line:any = csvData[i].split(',');
            if (App.Util.isInvalid(Line)) continue ;

            const data:any = {};
            data[Line[1]]=this._getValue(Line[0],Line[2]);
            data['doc'] = Line[3] != undefined ? Line[3].toString():'';
            json.push(data);
        }
        
        return json;
    }

    /**
     * 获取行数据
     * @param data 
     * @returns 
     */
    private _parseCell(data:string):any{
        return data.trim().split(/\n/gm).map((v) => {
            // 匹配出非单纯英文字符串的内容str
            const str = v.match(/"[^"]+"/ig);
            if (str) {
                // 将匹配到的str中的英文逗号转换成<|>标记符
                const result = str.map((vv) => {
                    return vv.replace(/,/g, '<|>')
                })
                // 将原字符串v中的匹配到的str进行替换
                str.forEach((vv, i) => {
                    v = v.replace(vv, result[i])
                })
            }
            // 按逗号截取每一列数据，顺便去除前后空字符
            const arr = v.split(/\s*,\s*/g).map((v) => {
                    // 去除双引号
                    return v.replace(/"/g, '')
                        // 重新将标记符转换到英文逗号
                        .replace(/<\|>/g, ',')
                });
            return arr;
        });
    }
}